//-*****************************************************************************
//
// Copyright (c) 2009-2011,
//  Sony Pictures Imageworks Inc. and
//  Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// *       Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// *       Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// *       Neither the name of Sony Pictures Imageworks, nor
// Industrial Light & Magic, nor the names of their contributors may be used
// to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//-*****************************************************************************
#ifndef _Alembic_Arnold_WriteGeo_h_
#define _Alembic_Arnold_WriteGeo_h_

#include <Alembic/AbcGeom/All.h>

#include "ProcArgs.h"
#include "SampleUtil.h"

// Grid Animation - sub assets attributes structure for polymesh
struct PolyMeshSubAssetAttributes {
	PolyMeshSubAssetAttributes()
	{
		// Initialize to similar values as per kick -info polymesh
		_shader.clear();
		_opaque = true;
		_smoothing = false;
		_subdiv_type = 0;
		_subdiv_iterations = 1;
		_subdiv_pixel_error = 0;
		_subdiv_dicing_camera = "";
		_subdiv_adaptive_metric = 0;
		_subdiv_uv_smoothing = 0;
		_subdiv_smooth_derivs = false;
		_disp_padding = 0;
		_disp_height = 1;
		_disp_zero_value = 0;
		_disp_autobump = false;
		_use_light_group = false;
		_light_group.clear();
		_use_shadow_group = false;
		_shadow_group.clear();
		_visibility = 65535;
		_id = 0;
		_sidedness = 65535;
		_receive_shadows = true;
		_self_shadows = true;
		_invert_normals = false;
		_ray_bias = 1e-06;
		_trace_sets.clear();
		_transform_time_samples.clear();
		_deform_time_samples.clear();
		_sss_sample_spacing = 0.1;
		_sss_sample_distribution = 0;

	}
	/* Prefer layout : Most frequently used firs
	shader
	opaque
	smoothing
	subdiv_type
	subdiv_iterations
	subdiv_pixel_error
	subdiv_dicing_camera
	subdiv_adaptive_metric
	subdiv_uv_smoothing
	subdiv_smooth_derivs
	disp_padding
	disp_height
	disp_zero_value
	disp_autobump
	use_light_group
	light_group
	use_shadow_group
	shadow_group
	visibility
	id
	sidedness
	receive_shadows
	self_shadows
	invert_normals
	ray_bias
	trace_sets
	transform_time_samples
	deform_time_samples
	sss_sample_spacing
	sss_sample_distribution
	 */
	/*
	UINT[]        nsides                            (empty)
	UINT[]        vidxs                             (empty)
	UINT[]        nidxs                             (empty)
	UINT[]        uvidxs                            (empty)
	UINT[]        crease_idxs                       (empty)
	BYTE[]        shidxs                            (empty)
	POINT[]       vlist                             (empty)
	VECTOR[]      nlist                             (empty)
	POINT2[]      uvlist                            (empty)
	BOOL          smoothing                         false
	ENUM          subdiv_type                       none
	INT           subdiv_iterations                 1
	FLOAT         subdiv_pixel_error                0
	NODE          subdiv_dicing_camera              (null)
	ENUM          subdiv_adaptive_metric            auto
	ENUM          subdiv_uv_smoothing               pin_corners
	BOOL          subdiv_smooth_derivs              false
	NODE[]        disp_map                          (empty)
	FLOAT         disp_padding                      0
	FLOAT         disp_height                       1
	FLOAT         disp_zero_value                   0
	BOOL          disp_autobump                     false
	INT           visibility                        65535
	INT           sidedness                         65535
	BOOL          receive_shadows                   true
	BOOL          self_shadows                      true
	BOOL          invert_normals                    false
	FLOAT         ray_bias                          1e-06
	MATRIX[]      matrix                            (empty)
	NODE[]        shader                            (empty)
	BOOL          opaque                            true
	BOOL          use_light_group                   false
	NODE[]        light_group                       (empty)
	BOOL          use_shadow_group                  false
	NODE[]        shadow_group                      (empty)
	STRING[]      trace_sets                        (empty)
	FLOAT[]       transform_time_samples            (2 elements)
	FLOAT[]       deform_time_samples               (2 elements)
	FLOAT         sss_sample_spacing                0.1
	ENUM          sss_sample_distribution           blue_noise
	INT           id                                0
	STRING        name
	 */
	/*
	 * NOTE : Arnold nodes are represented via string and look up when required
	 * NOTE : Arnold enum are represented via unsigned short to match underlying value
	 */
	std::string			_includeFilterRegex;
	std::string			_excludeFilterRegex;
	StringContainer 	_shader;
	bool            	_opaque;
	bool				_smoothing;
	unsigned short		_subdiv_type;
	unsigned short		_subdiv_iterations;
	float				_subdiv_pixel_error;
	std::string			_subdiv_dicing_camera;
	unsigned short		_subdiv_adaptive_metric;
	unsigned short		_subdiv_uv_smoothing;
	bool				_subdiv_smooth_derivs;
	float				_disp_padding;
	float				_disp_height;
	float				_disp_zero_value;
	bool				_disp_autobump;
	bool				_use_light_group;
	StringContainer		_light_group;
	bool				_use_shadow_group;
	StringContainer		_shadow_group;
	int					_visibility;
	int					_id;
	int					_sidedness;
	bool				_receive_shadows;
	bool				_self_shadows;
	bool				_invert_normals;
	float				_ray_bias;
	StringContainer		_trace_sets;
	FloatContainer		_transform_time_samples;
	FloatContainer		_deform_time_samples;
	float				_sss_sample_spacing;
	unsigned short		_sss_sample_distribution;
	static const size_t	_attributeCount = 32;
};

using namespace Alembic::AbcGeom;
//-*****************************************************************************


void ProcessPolyMesh( IPolyMesh &polymesh, ProcArgs &args,
        MatrixSampleMap * xformSamples, const std::string & facesetName = "");

void ProcessSubD( ISubD &subd, ProcArgs &args,
        MatrixSampleMap * xformSamples, const std::string & facesetName = "");

// void ProcessNuPatch( INuPatch &patch, ProcArgs &args );
// 
// void ProcessPoints( IPoints &patch, ProcArgs &args );
// 
// void ProcessCurves( ICurves &curves, ProcArgs &args );

void EscapeRegex(string &regex);
void EscapePerlRegex(string &regex);

bool MatchTextWithWildcards(const string &text, string wildcardPattern, bool caseSensitive);

bool MatchTextWithPerlRegex(const string &text, string wildcardPattern);

void TokenizeSubAssetAttributes(const std::string &attributesString, const std::string& separatorString, StringContainer& tokens);

void ProcessTokenAsBoolean(const std::string &tokenString, bool& attribute);
void ProcessTokenAsUnsignedShort(const std::string &tokenString, unsigned short& attribute);
void ProcessTokenAsInteger(const std::string &tokenString, int& attribute);
void ProcessTokenAsFloat(const std::string &tokenString, float& attribute);
void ProcessTokenAsFloats(const std::string &tokenString, const std::string& separatorString, FloatContainer attribute);
void ProcessTokenAsStringContainer(const std::string &tokenString, const std::string& separatorString, StringContainer& attribute);

bool TokenizeSubAssetAttributes(const std::string &attributesString,
								const std::string& attributeSeparatorString,
								const std::string& nodeNameSeparatorString,
								PolyMeshSubAssetAttributes& subAssetAttributes);
void SetPolyMeshNodeStandardArnoldAttributes(AtNode *meshNode,const PolyMeshSubAssetAttributes& subAssetAttributes);

#endif
